precision mediump float;

uniform sampler2D u_texture_0;	//dirt
uniform sampler2D u_texture_1;	//grass
uniform sampler2D u_texture_2;	//rock
uniform sampler2D u_texture_3;	//blend map
uniform vec3 u_camera_pos;
uniform float u_fog_distance;
uniform float u_fog_begin;
uniform vec3 u_light_point;

varying vec3 v_pos_world;
varying vec2 v_blend_uv;
varying vec2 v_terrain_uv;
varying vec3 v_norm_world;


//Globals variables
vec3 normal_world;


// LightDirection point from light source toward fragment
void AddPhongLightning(	in vec4 diffuseLight,
						in vec4 specLight,
						in float specPower, 
						in vec3 lightDirection,
						in float distance,		// for directional light, set this to -1.0
						inout vec4 totalDiff, 
						inout vec4 totalSpec)
{
	// diffuse light
	vec4 Cdiff = max( dot(-lightDirection, normal_world), 0.0) * diffuseLight;
	
	// spec light
	vec3 reflectVector = normalize( reflect(lightDirection, normal_world)); 
	vec3 toEye = normalize(u_camera_pos - v_pos_world);
	vec4 Spec = pow( max( dot(reflectVector, toEye), 0.0), specPower) * specLight;
	
	// attenuation for point light
	float atten = 1.0;
	if (distance >= 0.0)
		atten = (distance * distance) * 0.001 + distance * 0.001 + 0.001;
	
	// add to totals
	totalDiff += Cdiff / atten;
	totalSpec += Spec / atten;
}

vec4 GetPhongLightning(	in vec4 Cobj, 
						in vec4 totalDiff, 
						in vec4 totalSpec, 
						in vec4 ambienceLight, 
						in float weight)
{
	return vec4( ((ambienceLight * weight + totalDiff * (1.0 - weight)) * Cobj + totalSpec).rgb, Cobj.a);
}

vec4 LinearFog(in vec4 Cobj, in float fog_begin, in float fog_distance)
{
	const vec4 Cfog = vec4(1.0, 1.0, 1.0, 1.0);
	
	float dist = distance(v_pos_world, u_camera_pos);
	float lerpValue = clamp((dist - u_fog_begin) / u_fog_distance, 0.0, 1.0);
	
	return  (lerpValue * Cfog + (1.0 - lerpValue) * Cobj);
}

void main()
{
	vec4 c0 = texture2D(u_texture_0, v_terrain_uv);
	vec4 c1 = texture2D(u_texture_1, v_terrain_uv);
	vec4 c2 = texture2D(u_texture_2, v_terrain_uv);
	vec3 B = texture2D(u_texture_3, vec2(v_blend_uv.x, v_blend_uv.y)).rgb;
	
	float totalInverse = 1.0 / (B.r + B.g + B.b);
	c0 *= B.b * totalInverse;
	c1 *= B.g * totalInverse;
	c2 *= B.r * totalInverse;
	
	vec4 Cobj = (c0 + c1 + c2);
	
	// Normalize the interpolated normal vector
	normal_world = normalize(v_norm_world);
	
	//Now add lightning
	vec3 lightDirection = normalize(vec3(1.0, 30.0, 1.0));
	vec4 totalDiff = vec4(0.0);
	vec4 totalSpec = vec4(0.0);
	
	AddPhongLightning(vec4(1.0, 0.94, 0.87, 1.0), vec4(1.0, 0.94, 0.87, 1.0), 500.0, lightDirection, -1.0, totalDiff, totalSpec);
	AddPhongLightning(vec4(1.0, 0.5, 0.0, 1.0), vec4(1.0, 0.5, 0.0, 1.0), 20.0, normalize(v_pos_world - u_light_point), distance(v_pos_world, u_light_point), totalDiff, totalSpec);
	
	vec4 CobjPhong = GetPhongLightning(Cobj, totalDiff, totalSpec, vec4(1.0), 0.3);
	
	// Apply fog
	gl_FragColor = LinearFog(CobjPhong, u_fog_begin, u_fog_distance);
}